<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>

<script src="js/phaser.js"></script>
<script>
    //https://gamedevacademy.org/how-to-create-a-turn-based-rpg-game-in-phaser-3-part-1/

    class BootScene extends Phaser.Scene {
        constructor() {
            super('BootScene');
        }

        preload() {
            this.load.image('tiles', 'assets/map.png');
            this.load.tilemapTiledJSON('map', 'assets/map.json');

            this.load.spritesheet('player', 'assets/player.png', {frameWidth: 16, frameHeight: 16});
        }

        create() {
            console.info('BootScene');
            this.scene.start('WorldScene');
        }
    }

    class WorldScene extends Phaser.Scene {
        constructor() {
            super('WorldScene');
        }

        preload() {
            // load the resources here
        }

        create() {
            console.info('WorldScene');
            // 使用已加载的地图创建世界场景
            let map = this.make.tilemap({key: 'map'});

            // 第一行创建图块集图像
            let tiles = map.addTilesetImage('spritesheet', 'tiles');
            // 接下来的两行将图层添加到地图中
            let grass = map.createStaticLayer('Grass', tiles, 0, 0);
            let obstacles = map.createStaticLayer('Obstacles', tiles, 0, 0);

            // setCollisionByExclusion 方法使除发送的图块之外的所有图块都可用于冲突检测。
            // 在我们的例子中，发送 -1 会使该层上的所有图块发生碰撞
            obstacles.setCollisionByExclusion([-1]);

            // 第一个参数是 x 坐标，第二个参数是 y，第三个参数是图像资源，最后一个参数是其帧。
            // 为了在我们的世界地图上移动，我们将使用 Phaser 3 Arcade 物理。
            // 为了让玩家与地图上的障碍物发生碰撞，我们将通过物理系统 this.physics.add.sprite 创建它。
            this.player = this.physics.add.sprite(50, 100, 'player', 6);

            // 这将使玩家留在地图的边界内。首先，我们设置世界边界，
            // 然后将角色的属性 collideWorldBounds 设置为 true。
            this.physics.world.bounds.width = map.widthInPixels;
            this.physics.world.bounds.height = map.heightInPixels;
            this.player.setCollideWorldBounds(true);

            // 在地图上移动
            this.cursors = this.input.keyboard.createCursorKeys();

            // 我们的玩家可以移动，但摄像机不会跟随。要使相机跟随精灵，我们需要调用其 startFollow 方法。
            // 第一行将照相机限制在地图边界内。第二个使摄像机跟随玩家。
            this.cameras.main.setBounds(0, 0, map.widthInPixels, map.heightInPixels);
            this.cameras.main.startFollow(this.player);
            // 第三行 this.cameras.main.roundPixels = true;是防止瓷砖出血的一点技巧 - 在瓷砖上显示边界线。
            this.cameras.main.roundPixels = true;

            //  animation with key 'left', we don't need left and right as we will use one and flip the sprite
            this.anims.create({
                key: 'left',
                frames: this.anims.generateFrameNumbers('player', {frames: [1, 7, 1, 13]}),
                frameRate: 10,
                repeat: -1
            });

            // animation with key 'right'
            this.anims.create({
                key: 'right',
                frames: this.anims.generateFrameNumbers('player', {frames: [1, 7, 1, 13]}),
                frameRate: 10,
                repeat: -1
            });
            this.anims.create({
                key: 'up',
                frames: this.anims.generateFrameNumbers('player', {frames: [2, 8, 2, 14]}),
                frameRate: 10,
                repeat: -1
            });
            this.anims.create({
                key: 'down',
                frames: this.anims.generateFrameNumbers('player', {frames: [0, 6, 0, 12]}),
                frameRate: 10,
                repeat: -1
            });

            this.spawns = this.physics.add.group({ classType: Phaser.GameObjects.Zone });
            for(var i = 0; i < 30; i++) {
                var x = Phaser.Math.RND.between(0, this.physics.world.bounds.width);
                var y = Phaser.Math.RND.between(0, this.physics.world.bounds.height);
                // parameters are x, y, width, height
                this.spawns.create(x, y, 20, 20);
            }
            this.physics.add.overlap(this.player, this.spawns, this.onMeetEnemy, false, this);
        }

        // 碰撞检测
        onMeetEnemy(player, zone) {
            // we move the zone to some other location
            zone.x = Phaser.Math.RND.between(0, this.physics.world.bounds.width);
            zone.y = Phaser.Math.RND.between(0, this.physics.world.bounds.height);

            // shake the world
            this.cameras.main.shake(300);

            // start battle
        }

        update(time, delta) {
            // 首先，我们将体速设置为 0。然后，如果适当的键按下，
            // 我们将速度设置为 x 或 y。您可以在浏览器中测试角色的移动。
            this.player.body.setVelocity(0);
            // 水平移动
            if (this.cursors.left.isDown) {
                this.player.body.setVelocityX(-80);
            } else if (this.cursors.right.isDown) {
                this.player.body.setVelocityX(80);
            }
            // 垂直移动
            if (this.cursors.up.isDown) {
                this.player.body.setVelocityY(-80);
            } else if (this.cursors.down.isDown) {
                this.player.body.setVelocityY(80);
            }

            // 移动的动画
            if (this.cursors.left.isDown) {
                this.player.anims.play('left', true);
            } else if (this.cursors.right.isDown) {
                this.player.anims.play('right', true);
            } else if (this.cursors.up.isDown) {
                this.player.anims.play('up', true);
            } else if (this.cursors.down.isDown) {
                this.player.anims.play('down', true);
            } else {
                this.player.anims.stop();
            }
        }
    }

    let gameConfig = {
        type: Phaser.AUTO,
        width: 320,
        height: 240,
        zoom: 2,
        pixelArt: true, //像素模式：防止缩放时纹理模糊
        physics: {
            default: 'arcade',
            arcade: {
                gravity: {y: 0},
                debug: true
            }
        },
        scene: [BootScene, WorldScene]
    }

    let game = new Phaser.Game(gameConfig);
</script>
</body>

</html>